// system.h 
//	All global variables used in Nachos are defined here.
//
// Copyright (c) 1992-1993 The Regents of the University of California.
// All rights reserved.  See copyright.h for copyright notice and limitation 
// of liability and disclaimer of warranty provisions.

#ifndef SYSTEM_H
#define SYSTEM_H

#include "copyright.h"
#include "utility.h"
#include "thread.h"
#include "scheduler.h"
#include "interrupt.h"
#include "stats.h"
#include "timer.h"
#include "synch.h"
#define RANDOM 1   //For page replacement policy
#define FIFO 2

// Initialization and cleanup routines
extern void Initialize(int argc, char **argv); 	// Initialization,
						// called before anything else
extern void Cleanup();				// Cleanup, called when
						// Nachos is done.

extern Thread *currentThread;			// the thread holding the CPU
extern Thread *threadToBeDestroyed;  		// the thread that just finished
extern Scheduler *scheduler;			// the ready list
extern Interrupt *interrupt;			// interrupt status
extern Statistics *stats;		// performance metrics
extern Timer *timer;				// the hardware alarm clock






#ifdef USER_PROGRAM
#include "machine.h"
extern Machine* machine;	// user program memory and registers
//Project2 part2
#include "syscall.h"
#include "list.h"
#include "../userprog/iptEntry.h"
#define MAXPROCESSNUM 100	//maximum number of process we can have
#define MAXEXECNUM 100		//maximum number of exec we can do in a process
#define MAXFORKNUM 200		//maximum number of fork we can do in a process
//Project2 part1: The declearation of KernelLock  (the entry of LockTable)
#define MAXLOCKNUM 4096
#define MAXCVNUM 4096
#define MAXMVNUM 4096


struct KernelLock{ 
	Lock* lock;     
	AddrSpace *procSpace; 
	bool inUse;
}; 
extern KernelLock LockTable[MAXLOCKNUM];
extern Lock* LockTableLock;

struct KernelCV{ 
	Condition* condition;     
	AddrSpace* procSpace; 
	int numOfWait;
}; 
extern KernelCV CVTable[MAXCVNUM];
extern Lock* CVTableLock;
//Project2 part2: The declaration of nachos physical memory physMap
//ProcessTable and its management class




//Project 3
#define SWAPSIZE 65536

extern int tlbCounter;//for Project 3
extern int pageReplaceType;  //for Project 3
extern IPTEntry* ipt;//for Project 3
extern Lock *iptLock;//for Project 3
struct processTableEntry{
	char *name;
	AddrSpace *space;		//if null, then this entry is not occupied	
	int childProcessCounter;
	SpaceId spaceId;
	BitMap *threadIdMap;	//to allocate threadId to a thread
	int fixedPageEnd;		//the end of physical page allocated in addrSpace constructors
	int threadCounter;
	List *threadList;
};



class ProcessTable{
	private:
		struct processTableEntry* entries;
		int processCounter;	//current process number in the system
		int maxItemNum;
		public:
		ProcessTable(int itemNum);
		~ProcessTable();
		int isLastThread(SpaceId id);//return 1 for is last, -1 for invalid, 0 for not last
		bool isLastProcess(SpaceId id){return (processCounter==1);}	//return true if last process
		int deleteThread(SpaceId id, Thread *t);	//return the threadId of thread 
												//being deleted, or -1 if wrong
		int deleteProcess(SpaceId id);			//return the spaceId of process
												//being deleted, or -1 if wrong
		int addProcess(char *debugName, int len, AddrSpace *s, SpaceId id, Thread *t);
		int addProcess(char *debugName, int len, AddrSpace *s, SpaceId id);
		Thread* addThread(SpaceId id);
		SpaceId FindSpaceId();
		void updatePhysMap(SpaceId id, bool deleteProc);	//deleteProc = true if call
									// this to update physMap after delete a process
									//deleteProc = false if update after delete a thread
		bool isThreadFull(SpaceId id){ return (entries[id].threadCounter > MAXFORKNUM);}	
				//check whether thread number reach the maximum thread limits in a process
		bool isProcessFull(SpaceId id){ return (entries[id].childProcessCounter > MAXEXECNUM)||(processCounter > MAXPROCESSNUM);}
				//check whether process number reach the maximum process limits in a processs
		bool isValidId(SpaceId id);
};


#endif

#ifdef FILESYS_NEEDED 		// FILESYS or FILESYS_STUB 
#include "filesys.h"
extern FileSystem *fileSystem;
#endif

#ifdef FILESYS
#include "synchdisk.h"
extern SynchDisk *synchDisk;
#endif

#ifdef NETWORK
#include "post.h"
extern PostOffice* postOffice;

//------------Project3 part3--------------------//
#define MAXARGUMENT 4
#define MAXSTRINGLENGTH 16
#define MAXCLINETNUM 16
#define MAXMAILBOXNUM 500


//Server IP & PORT
#define SEVERID 0
#define SEVERMAILBOX 0  //The well-know port of server
//#define CLIENTMAILBOX 1   //We can not hard code it in project4

//Request type
#define CREATELOCK  1
#define DESTROYLOCK 2 
#define ACQUIRELOCK 3
#define RELEASELOCK 4
#define CREATECV	5
#define DESTROYCV 	6
#define WAITCV		7
#define SIGNALCV 	8
#define BROADCASTCV	9
#define CREATEMV	10
#define DESTROYMV	11
#define GETVALUEMV	12
#define SETVALUEMV	13


#define WRONGVALUE  2147483647
//Reply status
#define OK 1021
#define NOTOK -1021

#define IAMLOCKOWNER 8394
#define SUCCAQUR  2438
#define WAITINQUEUE 343
#define IWASWAKEDUP 706
#define IWASRELEASE 8848


//Project4 part2
#define TIMESTAMPMSG 0
#define REQUESTMSG 1
//2 types of forward message
//Project3 part3


struct KernelServerLock{ 
	ServerLock* theServerLock;    
	bool inUse;
}; 

extern KernelServerLock ServerLockTable[MAXLOCKNUM];

struct KernelServerCondition{ 
	ServerCondition* theServerCondition;    
	int numOfWait;
}; 
extern KernelServerCondition ServerContitionTable[MAXCVNUM];

struct KernelMV {
	int * mvArray;
	char*  mvName;
	int arraySize;
};
extern KernelMV MVTable[MAXMVNUM];


struct Socket {
	int machineID;
	int mailboxNum;
};


struct RpcReqMessage {
	int reqType;
	int intArgNum;
	int intArg[MAXARGUMENT];
	char strArg[MAXSTRINGLENGTH];
};

struct RpcRplyMessage
{
	int rplyType;
	int status;
	int retValue;

};

extern struct Socket* receivedSocketTable[MAXCLINETNUM][MAXMAILBOXNUM];

//Project4
extern int processMailbox;
extern Lock *processMailboxLock;
extern bool bullyOn;;
extern int serverSize;
extern int machineID;
struct RpcFwdMessage
{
	int fwdType;	//can be TIMESTAMPMSG/0 or REQUESTMSG/1
	int64_t timeStamp;
	struct Socket clientSock;	//came from which client
	struct Socket serverSock;	//who forwarded this msg
	struct RpcReqMessage reqMessage;

};

#endif

#endif // SYSTEM_H
